package com.huawei.zyb.taskManager.application.requirement;

import com.huawei.zyb.taskManager.application.requirement.dto.RequirementDTO;
import com.huawei.zyb.taskManager.domain.developer.repository.DeveloperRepository;
import com.huawei.zyb.taskManager.domain.developer.valueobject.DeveloperId;
import com.huawei.zyb.taskManager.domain.project.repository.ProjectRepository;
import com.huawei.zyb.taskManager.domain.project.valueobject.ProjectId;
import com.huawei.zyb.taskManager.domain.requirement.entity.Requirement;
import com.huawei.zyb.taskManager.domain.requirement.repository.RequirementRepository;
import com.huawei.zyb.taskManager.domain.requirement.valueobject.*;
import com.huawei.zyb.taskManager.domain.shared.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 需求应用服务
 */
@Service
@Transactional
public class RequirementApplicationService {
    
    private final RequirementRepository requirementRepository;
    private final ProjectRepository projectRepository;
    private final DeveloperRepository developerRepository;
    
    @Autowired
    public RequirementApplicationService(RequirementRepository requirementRepository,
                                       ProjectRepository projectRepository,
                                       DeveloperRepository developerRepository) {
        this.requirementRepository = requirementRepository;
        this.projectRepository = projectRepository;
        this.developerRepository = developerRepository;
    }
    
    /**
     * 创建需求
     */
    public RequirementDTO createRequirement(String title, String description,
                                           RequirementPriority priority, Long projectId) {
        // 验证项目是否存在
        if (!projectRepository.existsById(ProjectId.of(projectId))) {
            throw new BusinessException("项目不存在");
        }
        
        Requirement requirement = Requirement.create(
            RequirementTitle.of(title),
            RequirementDescription.of(description),
            priority,
            projectId,
            null // ownerId初始为null
        );
        
        Requirement savedRequirement = requirementRepository.save(requirement);
        return convertToDTO(savedRequirement);
    }
    
    /**
     * 创建需求（接受字符串参数）
     */
    public RequirementDTO createRequirement(String title, String description,
                                           String priority, Long projectId, String ownerId) {
        // 验证参数
        if (title == null || title.trim().isEmpty()) {
            throw new IllegalArgumentException("需求标题不能为空");
        }
        if (description == null || description.trim().isEmpty()) {
            throw new IllegalArgumentException("需求描述不能为空");
        }
        if (priority == null || priority.trim().isEmpty()) {
            throw new IllegalArgumentException("需求优先级不能为空");
        }
        
        // 验证项目是否存在
        if (!projectRepository.existsById(ProjectId.of(projectId))) {
            throw new BusinessException("项目不存在");
        }
        
        RequirementPriority requirementPriority = RequirementPriority.valueOf(priority);
        Requirement requirement = Requirement.create(
            RequirementTitle.of(title),
            RequirementDescription.of(description),
            requirementPriority,
            projectId,
            ownerId
        );
        
        Requirement savedRequirement = requirementRepository.save(requirement);
        return convertToDTO(savedRequirement);
    }
    
    /**
     * 创建需求（支持预期完成日期）
     */
    public RequirementDTO createRequirement(String title, String description,
                                           String priority, Long projectId, String ownerId,
                                           String expectedCompletionDate) {
        // 验证参数
        if (title == null || title.trim().isEmpty()) {
            throw new IllegalArgumentException("需求标题不能为空");
        }
        if (description == null || description.trim().isEmpty()) {
            throw new IllegalArgumentException("需求描述不能为空");
        }
        if (priority == null || priority.trim().isEmpty()) {
            throw new IllegalArgumentException("需求优先级不能为空");
        }
        
        // 验证项目是否存在
        if (!projectRepository.existsById(ProjectId.of(projectId))) {
            throw new BusinessException("项目不存在");
        }
        
        // 解析预期完成日期
        LocalDateTime expectedDateTime = null;
        if (expectedCompletionDate != null && !expectedCompletionDate.trim().isEmpty()) {
            try {
                expectedDateTime = LocalDateTime.parse(expectedCompletionDate);
            } catch (Exception e) {
                throw new IllegalArgumentException("预期完成日期格式不正确");
            }
        }
        
        RequirementPriority requirementPriority = RequirementPriority.valueOf(priority);
        Requirement requirement = Requirement.create(
            RequirementTitle.of(title),
            RequirementDescription.of(description),
            requirementPriority,
            projectId,
            ownerId,
            expectedDateTime
        );
        
        Requirement savedRequirement = requirementRepository.save(requirement);
        return convertToDTO(savedRequirement);
    }
    
    /**
     * 分配负责人
     */
    public void assignOwner(Long requirementId, String ownerId) {
        Requirement requirement = getRequirementById(requirementId);
        
        // 验证开发者是否存在且可分配任务
        if (!developerRepository.existsById(DeveloperId.of(ownerId))) {
            throw new BusinessException("开发者不存在");
        }
        
        if (!developerRepository.findById(DeveloperId.of(ownerId)).get().canBeAssignedTasks()) {
            throw new BusinessException("开发者不可分配任务");
        }
        
        requirement.assignOwner(ownerId);
        requirementRepository.save(requirement);
    }
    
    /**
     * 审批需求
     */
    public void approveRequirement(Long requirementId) {
        Requirement requirement = getRequirementById(requirementId);
        requirement.updateStatus(RequirementStatus.ACTIVE);
        requirementRepository.save(requirement);
    }
    
    /**
     * 拒绝需求
     */
    public void rejectRequirement(Long requirementId) {
        Requirement requirement = getRequirementById(requirementId);
        requirement.updateStatus(RequirementStatus.CANCELLED);
        requirementRepository.save(requirement);
    }
    
    /**
     * 开始需求
     */
    public void startRequirement(Long requirementId) {
        Requirement requirement = getRequirementById(requirementId);
        requirement.updateStatus(RequirementStatus.ACTIVE);
        requirementRepository.save(requirement);
    }
    
    /**
     * 暂停需求
     */
    public void pauseRequirement(Long requirementId) {
        Requirement requirement = getRequirementById(requirementId);
        requirement.updateStatus(RequirementStatus.CANCELLED);
        requirementRepository.save(requirement);
    }
    
    /**
     * 恢复需求
     */
    public void resumeRequirement(Long requirementId) {
        Requirement requirement = getRequirementById(requirementId);
        requirement.updateStatus(RequirementStatus.ACTIVE);
        requirementRepository.save(requirement);
    }
    
    /**
     * 完成需求
     */
    public void completeRequirement(Long requirementId) {
        Requirement requirement = getRequirementById(requirementId);
        requirement.complete();
        requirementRepository.save(requirement);
    }
    
    /**
     * 完成需求（接受字符串ID参数）
     */
    public RequirementDTO completeRequirement(String requirementId) {
        Requirement requirement = requirementRepository.findById(RequirementId.of(requirementId))
                .orElseThrow(() -> new BusinessException("需求不存在"));
        requirement.complete();
        requirementRepository.save(requirement);
        return convertToDTO(requirement);
    }
    
    /**
     * 取消需求
     */
    public void cancelRequirement(Long requirementId) {
        Requirement requirement = getRequirementById(requirementId);
        requirement.cancel();
        requirementRepository.save(requirement);
    }
    
    /**
     * 取消需求（接受字符串ID参数）
     */
    public RequirementDTO cancelRequirement(String requirementId) {
        Requirement requirement = requirementRepository.findById(RequirementId.of(requirementId))
                .orElseThrow(() -> new BusinessException("需求不存在"));
        requirement.cancel();
        requirementRepository.save(requirement);
        return convertToDTO(requirement);
    }
    
    /**
     * 更新需求信息
     */
    public void updateRequirement(Long requirementId, String title, String description,
                                RequirementPriority priority) {
        Requirement requirement = getRequirementById(requirementId);
        requirement.updateInfo(
            RequirementTitle.of(title),
            RequirementDescription.of(description),
            priority
        );
        requirementRepository.save(requirement);
    }
    
    /**
     * 更新需求信息（接受字符串参数）
     */
    public RequirementDTO updateRequirement(String requirementId, String title, String description,
                                           String priority) {
        Requirement requirement = requirementRepository.findById(RequirementId.of(requirementId))
                .orElseThrow(() -> new BusinessException("需求不存在"));
        RequirementPriority requirementPriority = RequirementPriority.valueOf(priority);
        requirement.updateInfo(
            RequirementTitle.of(title),
            RequirementDescription.of(description),
            requirementPriority
        );
        requirementRepository.save(requirement);
        return convertToDTO(requirement);
    }
    
    /**
     * 删除需求
     */
    public void deleteRequirement(Long requirementId) {
        Requirement requirement = getRequirementById(requirementId);
        
        requirementRepository.deleteById(requirement.getId());
    }
    
    /**
     * 根据ID查找需求
     */
    @Transactional(readOnly = true)
    public RequirementDTO findById(Long requirementId) {
        Requirement requirement = getRequirementById(requirementId);
        return convertToDTO(requirement);
    }
    
    /**
     * 根据ID查找需求（接受字符串参数）
     */
    @Transactional(readOnly = true)
    public RequirementDTO findRequirementById(String requirementId) {
        Requirement requirement = requirementRepository.findById(RequirementId.of(requirementId))
                .orElseThrow(() -> new BusinessException("需求不存在"));
        return convertToDTO(requirement);
    }
    
    /**
     * 根据项目ID查找需求列表
     */
    @Transactional(readOnly = true)
    public List<RequirementDTO> findByProjectId(Long projectId) {
        List<Requirement> requirements = requirementRepository.findByProjectId(projectId);
        return requirements.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 根据负责人ID查找需求列表
     */
    @Transactional(readOnly = true)
    public List<RequirementDTO> findByOwnerId(String ownerId) {
        List<Requirement> requirements = requirementRepository.findByOwnerId(ownerId);
        return requirements.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 根据状态查找需求列表
     */
    @Transactional(readOnly = true)
    public List<RequirementDTO> findByStatus(RequirementStatus status) {
        List<Requirement> requirements = requirementRepository.findByStatus(status);
        return requirements.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 根据优先级查找需求列表
     */
    @Transactional(readOnly = true)
    public List<RequirementDTO> findByPriority(RequirementPriority priority) {
        List<Requirement> requirements = requirementRepository.findByPriority(priority);
        return requirements.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 查找所有需求
     */
    @Transactional(readOnly = true)
    public List<RequirementDTO> findAll() {
        List<Requirement> requirements = requirementRepository.findAll();
        return requirements.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 查找所有需求（别名方法）
     */
    @Transactional(readOnly = true)
    public List<RequirementDTO> findAllRequirements() {
        return findAll();
    }
    
    /**
     * 根据项目ID查找需求列表（别名方法）
     */
    @Transactional(readOnly = true)
    public List<RequirementDTO> findRequirementsByProjectId(Long projectId) {
        return findByProjectId(projectId);
    }
    
    /**
     * 根据状态查找需求列表（别名方法，接受字符串参数）
     */
    @Transactional(readOnly = true)
    public List<RequirementDTO> findRequirementsByStatus(String status) {
        RequirementStatus requirementStatus = RequirementStatus.valueOf(status);
        return findByStatus(requirementStatus);
    }
    
    /**
     * 激活需求
     */
    public RequirementDTO activateRequirement(String requirementId) {
        Requirement requirement = requirementRepository.findById(RequirementId.of(requirementId))
                .orElseThrow(() -> new BusinessException("需求不存在"));
        requirement.updateStatus(RequirementStatus.ACTIVE);
        requirementRepository.save(requirement);
        return convertToDTO(requirement);
    }
    
    /**
     * 激活需求（Long参数版本）
     */
    public void activateRequirement(Long requirementId) {
        RequirementId id = RequirementId.of(requirementId);
        Requirement requirement = requirementRepository.findById(id)
            .orElseThrow(() -> new BusinessException("需求不存在"));
        
        requirement.activate();
        requirementRepository.save(requirement);
    }
    
    /**
     * 统计需求数量
     */
    @Transactional(readOnly = true)
    public long countRequirements() {
        return requirementRepository.findAll().size();
    }
    
    /**
     * 统计项目需求数量
     */
    @Transactional(readOnly = true)
    public long countByProjectId(Long projectId) {
        return requirementRepository.findByProjectId(projectId).size();
    }
    
    /**
     * 统计负责人需求数量
     */
    @Transactional(readOnly = true)
    public long countByOwnerId(String ownerId) {
        return requirementRepository.findByOwnerId(ownerId).size();
    }
    
    private Requirement getRequirementById(Long requirementId) {
        return requirementRepository.findById(RequirementId.of(requirementId))
                .orElseThrow(() -> new BusinessException("需求不存在"));
    }
    
    private RequirementDTO convertToDTO(Requirement requirement) {
        // 查询项目名称
        String projectName = null;
        if (requirement.getProjectId() != null) {
            projectName = projectRepository.findById(ProjectId.of(requirement.getProjectId()))
                    .map(project -> project.getName().getValue())
                    .orElse(null);
        }
        
        // 查询负责人姓名
        String ownerName = null;
        if (requirement.getOwnerId() != null) {
            ownerName = developerRepository.findById(DeveloperId.of(requirement.getOwnerId()))
                    .map(developer -> developer.getName().getValue())
                    .orElse(null);
        }
        
        // 防止ID为null时出现NullPointerException
        Long requirementId = requirement.getId() != null ? requirement.getId().getValue() : null;
        
        return new RequirementDTO(
            requirementId,
            requirement.getTitle().getValue(),
            requirement.getDescription().getValue(),
            requirement.getStatus(),
            requirement.getPriority(),
            requirement.getProjectId(),
            requirement.getOwnerId(),
            projectName,
            ownerName,
            requirement.getExpectedCompletionDate(),
            requirement.getCreatedAt(),
            requirement.getUpdatedAt()
        );
    }
}